Conversation
fabienfleureau
commented
Nov 19, 2025
- Introduce unified provider abstraction and models for GitLab/GitHub
- Implement GitHub provider (API client + webhooks) and extend GitLab provider
- Add approval & pipeline info (fetchApprovalInfo, UnifiedApprovalInfo, PR.pipeline)
- Improve review messages with pipeline/mergeable emojis and accurate approval counts
- Restore project threshold warnings and add GitHub project channel counting
|
Hello @M0nkeySan I tried to cherry-pick what I did to enable github support, maybe some changes are not necessary for MM context. |
3f8fc12 to
16f53c1
Compare
- Introduce unified provider abstraction and models for GitLab/GitHub - Implement GitHub provider (API client + webhooks) and extend GitLab provider - Add approval & pipeline info (fetchApprovalInfo, UnifiedApprovalInfo, PR.pipeline) - Improve review messages with pipeline/mergeable emojis and accurate approval counts - Restore project threshold warnings and add GitHub project channel counting
16f53c1 to
ddd1ff1
Compare
|
Hello @fabienfleureau, I will review your PR asap. In the mean time, can you fix the test failing in the pipeline ? |
There was a problem hiding this comment.
This part (line 22) need to be adapted to handle github hook body :
const { merge_request, object_attributes, project } = req.body as {
merge_request: {
author_id: number;
iid: number;
};
object_attributes: { author_id: number; note: string; url: string };
project: GitlabProjectDetails;
};
This is payload I received for an issue comment webhook event :
{
"action": "created",
"issue": {
"url": "https://api.github.com/repos/M0nkeySan/homer/issues/1",
"repository_url": "https://api.github.com/repos/M0nkeySan/homer",
"labels_url": "https://api.github.com/repos/M0nkeySan/homer/issues/1/labels{/name}",
"comments_url": "https://api.github.com/repos/M0nkeySan/homer/issues/1/comments",
"events_url": "https://api.github.com/repos/M0nkeySan/homer/issues/1/events",
"html_url": "https://github.com/M0nkeySan/homer/pull/1",
"id": 3642028010,
"node_id": "PR_kwDONH_Bn860USOp",
"number": 1,
"title": "Automatic mr review",
"user": {
"login": "M0nkeySan",
"id": 10235926,
"node_id": "MDQ6VXNlcjEwMjM1OTI2",
"avatar_url": "https://avatars.githubusercontent.com/u/10235926?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/M0nkeySan",
"html_url": "https://github.com/M0nkeySan",
"followers_url": "https://api.github.com/users/M0nkeySan/followers",
"following_url": "https://api.github.com/users/M0nkeySan/following{/other_user}",
"gists_url": "https://api.github.com/users/M0nkeySan/gists{/gist_id}",
"starred_url": "https://api.github.com/users/M0nkeySan/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/M0nkeySan/subscriptions",
"organizations_url": "https://api.github.com/users/M0nkeySan/orgs",
"repos_url": "https://api.github.com/users/M0nkeySan/repos",
"events_url": "https://api.github.com/users/M0nkeySan/events{/privacy}",
"received_events_url": "https://api.github.com/users/M0nkeySan/received_events",
"type": "User",
"user_view_type": "public",
"site_admin": false
},
"labels": [
{
"id": 9675882250,
"node_id": "LA_kwDONH_Bn88AAAACQLo_Cg",
"url": "https://api.github.com/repos/M0nkeySan/homer/labels/homer-review",
"name": "homer-review",
"color": "DCEEF1",
"default": false,
"description": ""
}
],
"state": "open",
"locked": false,
"assignee": null,
"assignees": [],
"milestone": null,
"comments": 2,
"created_at": "2025-11-19T10:14:49Z",
"updated_at": "2025-11-19T10:18:17Z",
"closed_at": null,
"author_association": "OWNER",
"active_lock_reason": null,
"draft": false,
"pull_request": {
"url": "https://api.github.com/repos/M0nkeySan/homer/pulls/1",
"html_url": "https://github.com/M0nkeySan/homer/pull/1",
"diff_url": "https://github.com/M0nkeySan/homer/pull/1.diff",
"patch_url": "https://github.com/M0nkeySan/homer/pull/1.patch",
"merged_at": null
},
"body": null,
"reactions": {
"url": "https://api.github.com/repos/M0nkeySan/homer/issues/1/reactions",
"total_count": 0,
"+1": 0,
"-1": 0,
"laugh": 0,
"hooray": 0,
"confused": 0,
"heart": 0,
"rocket": 0,
"eyes": 0
},
"timeline_url": "https://api.github.com/repos/M0nkeySan/homer/issues/1/timeline",
"performed_via_github_app": null,
"state_reason": null
},
"comment": {
"url": "https://api.github.com/repos/M0nkeySan/homer/issues/comments/3551915836",
"html_url": "https://github.com/M0nkeySan/homer/pull/1#issuecomment-3551915836",
"issue_url": "https://api.github.com/repos/M0nkeySan/homer/issues/1",
"id": 3551915836,
"node_id": "IC_kwDONH_Bn87Tte88",
"user": {
"login": "M0nkeySan",
"id": 10235926,
"node_id": "MDQ6VXNlcjEwMjM1OTI2",
"avatar_url": "https://avatars.githubusercontent.com/u/10235926?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/M0nkeySan",
"html_url": "https://github.com/M0nkeySan",
"followers_url": "https://api.github.com/users/M0nkeySan/followers",
"following_url": "https://api.github.com/users/M0nkeySan/following{/other_user}",
"gists_url": "https://api.github.com/users/M0nkeySan/gists{/gist_id}",
"starred_url": "https://api.github.com/users/M0nkeySan/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/M0nkeySan/subscriptions",
"organizations_url": "https://api.github.com/users/M0nkeySan/orgs",
"repos_url": "https://api.github.com/users/M0nkeySan/repos",
"events_url": "https://api.github.com/users/M0nkeySan/events{/privacy}",
"received_events_url": "https://api.github.com/users/M0nkeySan/received_events",
"type": "User",
"user_view_type": "public",
"site_admin": false
},
"created_at": "2025-11-19T10:18:17Z",
"updated_at": "2025-11-19T10:18:17Z",
"body": "test",
"author_association": "OWNER",
"reactions": {
"url": "https://api.github.com/repos/M0nkeySan/homer/issues/comments/3551915836/reactions",
"total_count": 0,
"+1": 0,
"-1": 0,
"laugh": 0,
"hooray": 0,
"confused": 0,
"heart": 0,
"rocket": 0,
"eyes": 0
},
"performed_via_github_app": null
},
"repository": {
"id": 880787871,
"node_id": "R_kgDONH_Bnw",
"name": "homer",
"full_name": "M0nkeySan/homer",
"private": false,
"owner": {
"login": "M0nkeySan",
"id": 10235926,
"node_id": "MDQ6VXNlcjEwMjM1OTI2",
"avatar_url": "https://avatars.githubusercontent.com/u/10235926?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/M0nkeySan",
"html_url": "https://github.com/M0nkeySan",
"followers_url": "https://api.github.com/users/M0nkeySan/followers",
"following_url": "https://api.github.com/users/M0nkeySan/following{/other_user}",
"gists_url": "https://api.github.com/users/M0nkeySan/gists{/gist_id}",
"starred_url": "https://api.github.com/users/M0nkeySan/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/M0nkeySan/subscriptions",
"organizations_url": "https://api.github.com/users/M0nkeySan/orgs",
"repos_url": "https://api.github.com/users/M0nkeySan/repos",
"events_url": "https://api.github.com/users/M0nkeySan/events{/privacy}",
"received_events_url": "https://api.github.com/users/M0nkeySan/received_events",
"type": "User",
"user_view_type": "public",
"site_admin": false
},
"html_url": "https://github.com/M0nkeySan/homer",
"description": "Homer is a Slack bot intended to help you to easily share and follow Gitlab merge requests.",
"fork": true,
"url": "https://api.github.com/repos/M0nkeySan/homer",
"forks_url": "https://api.github.com/repos/M0nkeySan/homer/forks",
"keys_url": "https://api.github.com/repos/M0nkeySan/homer/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/M0nkeySan/homer/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/M0nkeySan/homer/teams",
"hooks_url": "https://api.github.com/repos/M0nkeySan/homer/hooks",
"issue_events_url": "https://api.github.com/repos/M0nkeySan/homer/issues/events{/number}",
"events_url": "https://api.github.com/repos/M0nkeySan/homer/events",
"assignees_url": "https://api.github.com/repos/M0nkeySan/homer/assignees{/user}",
"branches_url": "https://api.github.com/repos/M0nkeySan/homer/branches{/branch}",
"tags_url": "https://api.github.com/repos/M0nkeySan/homer/tags",
"blobs_url": "https://api.github.com/repos/M0nkeySan/homer/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/M0nkeySan/homer/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/M0nkeySan/homer/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/M0nkeySan/homer/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/M0nkeySan/homer/statuses/{sha}",
"languages_url": "https://api.github.com/repos/M0nkeySan/homer/languages",
"stargazers_url": "https://api.github.com/repos/M0nkeySan/homer/stargazers",
"contributors_url": "https://api.github.com/repos/M0nkeySan/homer/contributors",
"subscribers_url": "https://api.github.com/repos/M0nkeySan/homer/subscribers",
"subscription_url": "https://api.github.com/repos/M0nkeySan/homer/subscription",
"commits_url": "https://api.github.com/repos/M0nkeySan/homer/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/M0nkeySan/homer/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/M0nkeySan/homer/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/M0nkeySan/homer/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/M0nkeySan/homer/contents/{+path}",
"compare_url": "https://api.github.com/repos/M0nkeySan/homer/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/M0nkeySan/homer/merges",
"archive_url": "https://api.github.com/repos/M0nkeySan/homer/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/M0nkeySan/homer/downloads",
"issues_url": "https://api.github.com/repos/M0nkeySan/homer/issues{/number}",
"pulls_url": "https://api.github.com/repos/M0nkeySan/homer/pulls{/number}",
"milestones_url": "https://api.github.com/repos/M0nkeySan/homer/milestones{/number}",
"notifications_url": "https://api.github.com/repos/M0nkeySan/homer/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/M0nkeySan/homer/labels{/name}",
"releases_url": "https://api.github.com/repos/M0nkeySan/homer/releases{/id}",
"deployments_url": "https://api.github.com/repos/M0nkeySan/homer/deployments",
"created_at": "2024-10-30T11:07:28Z",
"updated_at": "2025-10-17T13:04:09Z",
"pushed_at": "2025-10-21T12:25:34Z",
"git_url": "git://github.com/M0nkeySan/homer.git",
"ssh_url": "git@github.com:M0nkeySan/homer.git",
"clone_url": "https://github.com/M0nkeySan/homer.git",
"svn_url": "https://github.com/M0nkeySan/homer",
"homepage": "",
"size": 2061,
"stargazers_count": 0,
"watchers_count": 0,
"language": "TypeScript",
"has_issues": false,
"has_projects": true,
"has_downloads": true,
"has_wiki": false,
"has_pages": false,
"has_discussions": false,
"forks_count": 0,
"mirror_url": null,
"archived": false,
"disabled": false,
"open_issues_count": 1,
"license": {
"key": "mit",
"name": "MIT License",
"spdx_id": "MIT",
"url": "https://api.github.com/licenses/mit",
"node_id": "MDc6TGljZW5zZTEz"
},
"allow_forking": true,
"is_template": false,
"web_commit_signoff_required": false,
"topics": [],
"visibility": "public",
"forks": 0,
"open_issues": 1,
"watchers": 0,
"default_branch": "main"
},
"sender": {
"login": "M0nkeySan",
"id": 10235926,
"node_id": "MDQ6VXNlcjEwMjM1OTI2",
"avatar_url": "https://avatars.githubusercontent.com/u/10235926?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/M0nkeySan",
"html_url": "https://github.com/M0nkeySan",
"followers_url": "https://api.github.com/users/M0nkeySan/followers",
"following_url": "https://api.github.com/users/M0nkeySan/following{/other_user}",
"gists_url": "https://api.github.com/users/M0nkeySan/gists{/gist_id}",
"starred_url": "https://api.github.com/users/M0nkeySan/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/M0nkeySan/subscriptions",
"organizations_url": "https://api.github.com/users/M0nkeySan/orgs",
"repos_url": "https://api.github.com/users/M0nkeySan/repos",
"events_url": "https://api.github.com/users/M0nkeySan/events{/privacy}",
"received_events_url": "https://api.github.com/users/M0nkeySan/received_events",
"type": "User",
"user_view_type": "public",
"site_admin": false
}
}
| { | ||
| text: { | ||
| type: 'plain_text', | ||
| text: 'Create a pipeline', | ||
| }, | ||
| value: injectActionsParameters( | ||
| 'review-create-pipeline', | ||
| projectId, | ||
| pullRequest.sourceBranch, | ||
| ), | ||
| }, | ||
| { | ||
| text: { | ||
| type: 'plain_text', | ||
| text: 'Rebase source branch', | ||
| }, | ||
| value: injectActionsParameters( | ||
| 'review-rebase-source-branch', | ||
| projectId, | ||
| pullRequest.iid, | ||
| ), | ||
| }, |
There was a problem hiding this comment.
Maybe we should remove this 2 actions for Github because they are not implemented yet.
| // 'commented' state - treat as update | ||
| action = 'update'; |
There was a problem hiding this comment.
Is it wanted to handle the commented state here ?
Because with this behaviour, we don't have the comments send to the slack thread.
|
Can't wait to see github support from my beloved Homer bot :) |
| */ | ||
|
|
||
| describe('UnifiedModels Type Definitions', () => { | ||
| it('should pass TypeScript compilation', () => { |
There was a problem hiding this comment.
Why do we need this test?
|
Hi, I didn't have time to check your comment yet! I'l do it asap |